package com.egao.xcx.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egao.common.core.Constants;
import com.egao.common.core.damon.constant.UserConstant;
import com.egao.common.core.damon.constant.WechatConstant;
import com.egao.common.core.damon.utils.HttpClientUtil;
import com.egao.common.core.damon.utils.Utils;
import com.egao.common.core.security.JwtUtil;
import com.egao.common.core.web.BaseController;
import com.egao.common.core.web.JsonResult;
import com.egao.common.system.entity.User;
import com.egao.common.system.service.LoginRecordService;
import com.egao.common.system.service.UserService;
import com.egao.gzh.service.Wxservice;
import com.egao.gzh.utils.AesException;
import com.egao.gzh.utils.WXPublicUtils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import io.swagger.annotations.ApiOperation;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;

/**
 * @author : Doman
 * @version ：1.0
 * @date : 2020-04-12 17:33
 */
@RestController
@RequestMapping("/api/nt/xcx")
public class XcxController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private LoginRecordService loginRecordService;

    /*
    * 参考下面的网址
    * 网址:https://blog.csdn.net/yhflyl/article/details/85060294
    * */
    @PostMapping("/login")
    @ResponseBody
    public JsonResult user_login(String code, User insert_user, HttpServletRequest request) throws Exception {
//        String code2 = request.getParameter("code");
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", WechatConstant.WX_LOGIN_APPID);
        param.put("secret", WechatConstant.WX_LOGIN_SECRET);
        param.put("js_code", code);
        param.put("grant_type", WechatConstant.WX_LOGIN_GRANT_TYPE);
        // 发送请求
        String wxResult = HttpClientUtil.doGet(WechatConstant.WX_LOGIN_URL, param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);

        // 获取参数返回的
        String session_key = jsonObject.get("session_key").toString();
        String xcxopen_id = jsonObject.get("openid").toString();
        // 根据返回的user实体类，判断用户是否是新用户，不是的话，更新最新登录时间，是的话，将用户信息存到数据库
        User user = null;
        try {
            user = userService.getByXcxopenId(new User(xcxopen_id,""));
            /*if(user != null) {
                user = userService.getByPhone(user);
            }*/
        } catch (Exception e) {
        }
       if(user != null){
           user.setNickName(insert_user.getNickName());
           user.setCountry(insert_user.getCountry());
           user.setProvince(insert_user.getProvince());
           user.setSex(insert_user.getSex());
           user.setCity(insert_user.getCity());
           user.setAvatar(insert_user.getAvatar());
           user.setPhone(insert_user.getPhone());
           userService.apiUpdate(user);
        }else{
            // 添加到数据库
            List<Integer> roleids = new ArrayList<>();
            roleids.add(UserConstant.NORMAL_USER);
            //新增的用户都为普通游客
            insert_user.setRoleIds(roleids);
            insert_user.setUsername(System.currentTimeMillis()+"");
            insert_user.setOrganizationId(UserConstant.ORGANIZATION_ID);
            insert_user.setPassword(UserConstant.DEFAULT_PSW);
            insert_user.setXcxopenid(xcxopen_id);
            userService.apiSave(insert_user);
            user = insert_user;
        }
        // 封装返回小程序
        Map<String, String> result = new HashMap<>();
        result.put("session_key", session_key);
        result.put("open_id", xcxopen_id);

        String access_token = JwtUtil.buildToken(user.getUsername(), Constants.TOKEN_EXPIRE_TIME, Constants.TOKEN_KEY);
        // 记录登录日志
        loginRecordService.saveAsync(user.getUsername(), request);
        System.out.println("openid="+ xcxopen_id);
        return JsonResult.ok("登录成功").put("session_key", session_key).put("access_token", access_token)
                .put("userinfo", user).put("openid", xcxopen_id);
    }

            @PostMapping("/loginByOpenId")
            @ResponseBody
            public JsonResult loginByOpenId(String openId,String code, HttpServletRequest request) throws Exception {
                if (Utils.isNotEmpty(code)) {
                    Map<String, String> param = new HashMap<>();
                    param.put("appid", WechatConstant.WX_LOGIN_APPID);
                    param.put("secret", WechatConstant.WX_LOGIN_SECRET);
                    param.put("js_code", code);
                    param.put("grant_type", WechatConstant.WX_LOGIN_GRANT_TYPE);
            // 发送请求
            String wxResult = HttpClientUtil.doGet(WechatConstant.WX_LOGIN_URL, param);
            JSONObject jsonObject = JSONObject.parseObject(wxResult);

            // 获取参数返回的
            openId = jsonObject.get("openid").toString();
        }
        User user = null;
        try {
            user = userService.getByXcxopenId(new User(openId,""));
            String access_token = JwtUtil.buildToken(user.getUsername(), Constants.TOKEN_EXPIRE_TIME, Constants.TOKEN_KEY);
            // 记录登录日志
            loginRecordService.saveAsync(user.getUsername(), request);
            return JsonResult.ok("登录成功").put("access_token", access_token).put("openId", openId)
                    .put("userinfo", user);
        } catch (Exception e) {
        }
        return JsonResult.error("没有该用户!");
    }

    /**
     * 微信小程序token
     */
    @ApiOperation(value = "微信公众平台token",notes = "" +
            "signature 公众号加密签名\n" +
            "timestamp 公众号时间戳\n" +
            "nonce 公众号随机数字\n" +
            "echostr 公众号随机字符串\n" +
            "",httpMethod = "GET")
    @GetMapping("/message")
    public String gzhValidate(String signature, String timestamp,
                              String nonce, String echostr) throws AesException {
        //调式url:http://damon.free.idcfengye.com/api/nt/wechart/message
        //正式url:https://godutch.gangcai.store:4332/api/nt/wechart/message
        if (WXPublicUtils.verifyUrl(signature, timestamp, nonce)) {
            System.out.println("公众号验证成功!");
            return echostr;
        }
        return null;
    }

    @PostMapping(value = "message")
    public void processMsg(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        Wxservice wxservice = new Wxservice();
        // 调用核心服务类接收处理请求
        Map<String, String> requestMap = wxservice.parseRequest(request.getInputStream());
        System.out.println(requestMap);
        //准备回复的数据包
        String resXml = wxservice.getRespose(requestMap);
//                "<xml>" +
//                "<ToUserName><![CDATA["+requestMap.get("FromUserName")+"]]></ToUserName>" +
//                "<FromUserName><![CDATA["+requestMap.get("ToUserName")+"]]></FromUserName>" +
//                "<CreateTime>"+ System.currentTimeMillis()/1000 +"</CreateTime>" +
//                "<MsgType><![CDATA[text]]></MsgType>" +
//                "<Content><![CDATA[why?]]></Content>" +
//                "</xml>";

        PrintWriter out = response.getWriter();
        System.out.println(resXml);
        out.print(resXml);
        out.flush();
        out.close();
//        ServletInputStream is = request.getInputStream();
//        byte[] b = new byte[1024];
//        int len;
//        StringBuilder sb = new StringBuilder();
//        while ((len=is.read(b))!=-1) {
//            sb.append(new String(b, 0, len));
//        }
    }


    /*
    *
    *
    * 得到手机号码
    *
    * */
    @GetMapping("/wxOauth")
    @ResponseBody
    public String wxOauth(String encryptedData, String iv, String codes, HttpServletRequest request, HttpServletResponse response) throws Exception{
        Object res = getPhoneNumber(encryptedData,codes,iv);
        return res.toString();
    }

    public Object getPhoneNumber(String encryptedData, String code, String iv) {
        //传入code后然后获取openid和session_key的，把他们封装到json里面
        JSONObject json = getSessionKeyOropenid(code);
        String session_key = "";
        if (json != null) {
            session_key = json.getString("session_key");
            // 被加密的数据
            byte[] dataByte = Base64.decode(encryptedData);
            // 加密秘钥
            byte[] keyByte = Base64.decode(session_key);
            // 偏移量
            byte[] ivByte = Base64.decode(iv);
            try {
                // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
                int base = 16;
                if (keyByte.length % base != 0) {
                    int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                    byte[] temp = new byte[groups * base];
                    Arrays.fill(temp, (byte) 0);
                    System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                    keyByte = temp;
                }
                // 初始化
                Security.addProvider(new BouncyCastleProvider());
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
                AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
                parameters.init(new IvParameterSpec(ivByte));
                cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
                byte[] resultByte = cipher.doFinal(dataByte);
                if (null != resultByte && resultByte.length > 0) {
                    String result = new String(resultByte, "UTF-8");
                    return JSONObject.parseObject(result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 获取微信小程序 session_key 和 openid
     *
     * @param code 调用微信登陆返回的Code
     * @return
     */
    public static JSONObject getSessionKeyOropenid(String code) {
        //微信端登录code值
        String wxCode = code;
        Map<String, String> requestUrlParam = new HashMap<String, String>();
        requestUrlParam.put("appid", WechatConstant.WX_LOGIN_APPID);  //开发者设置中的appId
        requestUrlParam.put("secret", WechatConstant.WX_LOGIN_SECRET); //开发者设置中的appSecret
        requestUrlParam.put("js_code", wxCode); //小程序调用wx.login返回的code
        requestUrlParam.put("grant_type", WechatConstant.WX_LOGIN_GRANT_TYPE);    //默认参数 authorization_code

        //发送post请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session 接口获取openid用户唯一标识
        JSONObject jsonObject = JSON.parseObject(sendPost(WechatConstant.WX_LOGIN_URL, requestUrlParam));
        return jsonObject;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url 发送请求的 URL
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, Map<String, ?> paramMap) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";

        String param = "";
        Iterator<String> it = paramMap.keySet().iterator();

        while (it.hasNext()) {
            String key = it.next();
            param += key + "=" + paramMap.get(key) + "&";
        }

        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
}